
package Manejo.Transporte.Registros;

import java.util.HashMap;
import java.util.ArrayList;

import Manejo.Transporte.Naviera;
import Archivador.*;

/**
 * Registro de todas las Navieras a utilizar en el programa.
 * 
 * @author Jonathan López
 * @author Jorge Martinez
 */
public class RegNavieras {
    private HashMap<ID, Naviera> navieras;
    private HashMap<String, ID> nombreNavieras;
    private String nombreRegistro = "RegistroNavieras";
    
    /**
     * Constructor de RegNavieras
     */
    public RegNavieras()
    {
        navieras = new HashMap<ID, Naviera>();
        nombreNavieras = new HashMap<String, ID>();
    }
    
    /**
     * Lee las Navieras desde la base de datos
     */
    public void inicializar( Registros registros )
    {
        // Leer las Navieras de la base de datos
        String[] infoNavieras = Archivador.leerRegistro(nombreRegistro);
        if( infoNavieras != null ){
            for( String linea: infoNavieras ){
                if( !linea.equals("") && !leerNaviera( linea, registros ) )
                    System.out.println("*ERROR RegNavieras* - No se pudo leer Naviera");
            }
        }
    }
    
    /**
     * Guarda el registro de Navieras
     */
    public void guardarTodo(){
        // Serializa todas las Navieras
        ArrayList<String> lineaNavieras = new ArrayList<String>();
        
        for( String nombreNaviera: nombreNavieras.keySet() ){
            ID idNaviera = nombreNavieras.get( nombreNaviera );
            
            String srIdentificador = "[" + nombreNaviera + iArchivable.separador +
                    idNaviera.guardar() + "]";
            String srNaviera = navieras.get(idNaviera).guardar();
            
            lineaNavieras.add( srIdentificador + iArchivable.separadorObjetos +
                    srNaviera );
        }
        
        // Guarda el registro
        if( lineaNavieras.isEmpty() )
            lineaNavieras.add( "" );
        
        Archivador.guardarRegistro(nombreRegistro,
                lineaNavieras.toArray( new String[0] ));
    }
    
    /**
     * Agrega una nueva Naviera al registro y le asigna un ID
     * @param nuevaNaviera Naviera a agregar
     * @param nombre nombre con el cual registrar a la naviera, o "" si no
     * se quiere agregar ninguno. La función falla si ya existe el nombre.
     * @return nuevo ID de la Naviera, o idNulo si no se pudo agregar
     */
    public ID agregarNaviera( Naviera nuevaNaviera, String nombre  )
    {
        // No se puede agregar la naviera si ya existe el nombre registrado
        if( !nombre.equals("") )
            if( nombreNavieras.containsKey( nombre ) )
                return ID.idNulo;
            
        
        ID nuevoID = GeneradorID.nuevoID();
        while( navieras.containsKey( nuevoID ) ){
            // Muy improbable
            // TODO: notificar al log por cada uno de estos casos
            nuevoID = GeneradorID.nuevoID();
        }
        
        navieras.put( nuevoID, nuevaNaviera );
        if( !nombre.equals("") )
            nombreNavieras.put(nombre, nuevoID);
        
        return nuevoID;
    }
    
    /**
     * Regresa la Naviera asociada con el ID dado
     * @param idNaviera ID de la Naviera a buscar
     * @return Naviera asociada al ID o null si no se encuentra
     */
    public Naviera obtenerNaviera( ID idNaviera )
    {
        return navieras.get( idNaviera );
    }
    
    /**
     * Retorna la Naviera asociada con el nombre dado
     * @param nombre nombre de la Naviera a buscar
     * @return Naviera asociada al nombre, o null si no se encuentra
     */
    public Naviera obtenerNaviera( String nombre )
    {
        ID idNaviera = nombreNavieras.get( nombre );
        if( idNaviera != null )
            return obtenerNaviera( idNaviera );
        else
            return null;
    }
    
    /**
     * Regresa el nombre de la Naviera en base a su ID
     * @param idNaviera
     * @return 
     */
    public String obtenerNombre( ID idNaviera )
    {
        if( navieras.containsKey(idNaviera) ){
            for (String nombre : nombreNavieras.keySet()) {
                if( nombreNavieras.get(nombre).equals(idNaviera) )
                    return nombre;
            }
        }
        return "";
    }
    
    /**
     * Retorna todos los nombres de Navieras asociados en el registro
     * @return String[]
     */
    public String[] obtenerNombreDeNavieras()
    {
        return nombreNavieras.keySet().toArray( new String[0] );
    }
    
    /**
     * Regresa un arreglo con todas las navieras contenidas en el registro
     * @return Naviera[] con todas las navieras en el registro
     */
    public Naviera[] obtenerTodasNavieras()
    {
        return navieras.values().toArray( new Naviera[0] );
    }
    
    /**
     * Regresa el ID de una Naviera
     * @param navieraObjetivo 
     * @return ID de la Naviera
     */
    public ID obtenerID( Naviera navieraObjetivo )
    {
        for( ID id: navieras.keySet() ){
            if( navieras.get(id) == navieraObjetivo )
                return id; 
        }
       
        return ID.idNulo;
    }
    
    /**
     * Regresa el ID de una Naviera, dada por su nombre.
     * @param nombreNaviera Nombre de la Naviera a buscar
     * @return ID de la Naviera o idNulo si no existe
     */
    public ID obtenerID( String nombreNaviera ){
        for( String nombre: nombreNavieras.keySet() ){
            if( nombre.endsWith(nombreNaviera) )
                return nombreNavieras.get(nombre);
        }
        return ID.idNulo;
    }
    
    /**
     * Elimina una Naviera del registro según su ID
     * @param idNaviera ID de la ruta a eliminar
     * @return la Naviera asociada al ID dado, o null si no existía
     */
    public Naviera eliminarNaviera( ID idNaviera )
    {
        // Eliminar la referencia de nombre de esta naviera si existe
        if( nombreNavieras.containsValue(idNaviera) ){
            nombreNavieras.values().remove( idNaviera );
        }
        
        return navieras.remove( idNaviera );
    }

    /**
     * Lee una sola Naviera a partir de una línea de registro.
     * @param linea
     * @param registroBarcos
     * @return 
     */
    private boolean leerNaviera(String linea, Registros registros)
    {
        String[] partes = linea.split( iArchivable.separadorObjetos, 2 );
        if( partes.length != 2 )
            return false;
        
        // Interpreta el ID de la Naviera
        String srIdentificador = Util.eliminarExtremos( partes[0] );
        String[] partesIdentificador = srIdentificador.split( iArchivable.separador );
        if( partesIdentificador.length != 2 )
            return false;
        
        String nombre = partesIdentificador[0];
        ID idNaviera = ID.parseID( partesIdentificador[1] );
        if( idNaviera.equals( ID.idNulo ) )
            return false;
        
        // Interpreta la Naviera
        Naviera navieraActual = Naviera.parseNaviera( partes[1], registros );
        if( navieraActual == null )
            return false;
        
        // Agrega la nueva Naviera
        navieras.put( idNaviera, navieraActual );
        nombreNavieras.put( nombre, idNaviera );
        return true;
    }
    
    
}
